﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Autodesk.AutoCAD.Windows;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.ApplicationServices;
using ACADApplication = Autodesk.AutoCAD.ApplicationServices.Application;
using ACADDatabase = Autodesk.AutoCAD.DatabaseServices.Database;
using ACADDocument = Autodesk.AutoCAD.ApplicationServices.Document;

namespace YNCNumberSys
{
    /// <summary>
    /// 在块表记录已经存在的情况下,向图纸总插入对应块应用
    /// </summary>
    public class ZJInsertBlockReference
    {
        #region 变量定义
        /// <summary>
        /// 插入目标块表记录的对象ID.
        /// </summary>
        private ObjectId _id_BlockTableRecord;
        /// <summary>
        /// 块引用的插入点.
        /// </summary>
        private Point3d _pt_BlockReferenceInsertPoint;
        /// <summary>
        /// 块引用比例.
        /// </summary>
        private double _d_BlockReferenceScale;
        /// <summary>
        /// 块引用插入弧度,逆时针方向.
        /// </summary>
        private double _d_Rotation;
        /// <summary>
        /// 插入块引用的对象ID,返回结果值.
        /// </summary>
        private ObjectId _id_BlockReference;
        /// <summary>
        /// 事务,为空表示操作当前图纸空间.
        /// </summary>
        private Transaction _trs_Transaction;
        /// <summary>
        /// 图纸文档WorkingDatabase,为空表示当前的图纸空间.
        /// </summary>
        private ACADDatabase _wdb_DataBase;
        /// <summary>
        /// 该值如果为True,则(1)_trs_Transaction,_wdb_DataBase和图纸文档均为当前图纸空间,并且图纸文档未锁定;
        /// (2)事务提交在该类内完成.
        /// </summary>
        private bool _b_TransactionIsUsed;
        #endregion

        public ObjectId id_BlockReference
        {
            get { return _id_BlockReference; }
            set { _id_BlockReference = value; }
        }

        public ZJInsertBlockReference(ACADDatabase wdb_DataBase,Transaction trs_Transaction, 
            ObjectId id_BlockTableRecord,Point3d pt_BlockReferenceInsertPoint, double d_BlockReferenceScale, double d_Rotation)
        {
            _wdb_DataBase = wdb_DataBase;
            _trs_Transaction = trs_Transaction;
            _id_BlockTableRecord = id_BlockTableRecord;
            _pt_BlockReferenceInsertPoint = pt_BlockReferenceInsertPoint;
            _d_BlockReferenceScale = d_BlockReferenceScale;
            _d_Rotation = d_Rotation;
            _id_BlockReference = ObjectId.Null;
            _b_TransactionIsUsed = true;
        }
        public ZJInsertBlockReference(ObjectId id_BlockTableRecord, 
            Point3d pt_BlockReferenceInsertPoint, double d_BlockReferenceScale, double d_Rotation)
        {
            _wdb_DataBase = HostApplicationServices.WorkingDatabase; ;
            _trs_Transaction = null;
            _id_BlockTableRecord = id_BlockTableRecord;
            _pt_BlockReferenceInsertPoint = pt_BlockReferenceInsertPoint;
            _d_BlockReferenceScale = d_BlockReferenceScale;
            _d_Rotation = d_Rotation;
            _id_BlockReference = ObjectId.Null;
            _b_TransactionIsUsed = false;
        }
        private void DoInsertBlockReference()
        {
            BlockTable bt = (BlockTable)_trs_Transaction.GetObject(_wdb_DataBase.BlockTableId, OpenMode.ForWrite);
            BlockTableRecord pMRecord = (BlockTableRecord)_trs_Transaction.GetObject(_wdb_DataBase.CurrentSpaceId, OpenMode.ForWrite); 
            BlockTableRecord pRecord = (BlockTableRecord)_trs_Transaction.GetObject(_id_BlockTableRecord, OpenMode.ForWrite);
            pRecord.Explodable = true;

            BlockReference blkRef = new BlockReference(_pt_BlockReferenceInsertPoint, _id_BlockTableRecord);
            blkRef.Rotation = _d_Rotation;
            blkRef.ScaleFactors = new Scale3d(_d_BlockReferenceScale);
            pMRecord.AppendEntity(blkRef);
            _trs_Transaction.AddNewlyCreatedDBObject(blkRef, true);
            _id_BlockReference = blkRef.ObjectId;
        }
        public ObjectId Do()
        {
            _id_BlockReference = ObjectId.Null;

            if (!_b_TransactionIsUsed)
            {
                using (_trs_Transaction = _wdb_DataBase.TransactionManager.StartTransaction())
                {
                    DoInsertBlockReference();
                    ZJAppendAttribute cls_ZJAppendAttribute
                        = new ZJAppendAttribute(_wdb_DataBase, _trs_Transaction, _id_BlockTableRecord, _id_BlockReference);
                    cls_ZJAppendAttribute.Do();
                    _trs_Transaction.Commit();
                    _trs_Transaction.Dispose();
                }
            }
            else
            {
                DoInsertBlockReference();
                ZJAppendAttribute cls_ZJAppendAttribute
                    = new ZJAppendAttribute(_wdb_DataBase, _trs_Transaction, _id_BlockTableRecord, _id_BlockReference);
                cls_ZJAppendAttribute.Do();
            }

            return _id_BlockReference;
        }
    }
}
